package com.jdy.haoduoaiteacher.util;

import org.json.JSONObject;

import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * 1.16的整数倍？不是用0填充 2.用AES加密 3.最后再用Base64解密
 */

public class AES128 {

  /**
   * 加密
   * 
   * @param content
   *          需要加密的内容
   * @return
   */
  public static String encrypt(String content) {
    try {
      Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");

      int blockSize = cipher.getBlockSize();

      // We need to pad with zeros to a multiple of the cipher block size,
      // so first figure out what the size of the plaintext needs to be.
      byte[] dataBytes = content.getBytes();

      int plaintextLength = dataBytes.length;

      if (plaintextLength % blockSize != 0) {
        plaintextLength = plaintextLength
            + (blockSize - (plaintextLength % blockSize));
      }

      // In java, primitive arrays of integer types have all elements
      // initialized to zero, so no need to explicitly zero any part of
      // the array.
      byte[] plaintext = new byte[plaintextLength];

      // Copy our actual data into the beginning of the array. The
      // rest of the array is implicitly zero-filled, as desired.
      System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);

      String key = generateKey();

      String iv = key;

      SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");

      IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

      cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);

      byte[] encrypted = cipher.doFinal(plaintext);

      String result = Base64.encode(encrypted);

      String transformedData1 = result.substring(0, 4);

      String transformedData2 = result.substring(4);

      return transformedData1 + key + transformedData2;

    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;

  }

  /**
   * 解密
   * 
   * @param content
   *          待解密内容
   * @return
   */
  public static String decrypt(String content) {
    try {

      String key = content.substring(4, 4 + 16);

      String iv = key;

      content = content.replace(key, "");

      byte[] decryptFrom = Base64.decode(content);

      Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");

      SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");

      IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

      cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);// 初始化

      byte[] result = cipher.doFinal(decryptFrom);

      String r = new String(result); // 解密

      r = r.trim();

      return r;

    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  public static JSONObject decryptToJSON(String content) {
    try {

      String key = content.substring(4, 4 + 16);

      String iv = key;

      content = content.replace(key, "");

      byte[] decryptFrom = Base64.decode(content);

      Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");

      SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");

      IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

      cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);// 初始化

      byte[] result = cipher.doFinal(decryptFrom);

      String resultStr = new String(result); // 解密

      return new JSONObject(resultStr);

    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  public static String generateKey() {
    char[] chars = "0123456789abcdefghijklmnopqrstuvwxyz".toCharArray();
    StringBuilder sb = new StringBuilder();
    Random random = new Random();
    for (int i = 0; i < 16; i++) {
      char c = chars[random.nextInt(chars.length)];
      sb.append(c);
    }
    String output = sb.toString();
    return output;
  }

}
